﻿using PaperRenderingEngine;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using DeepZoomPivotConstructor.PivotLib;
using System.Collections.Generic;
using System.Linq;
using PaperRenderingInterfaces;
using t_TestingLibrary;
using System.ComponentModel.Composition;

namespace t_PaperRenderingInterfaces
{
    
    
    /// <summary>
    ///This is a test class for RenderEngineTest and is intended
    ///to contain all RenderEngineTest Unit Tests
    ///</summary>
    [TestClass()]
    public class RenderEngineTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        [TestInitialize]
        public void TestSetup()
        {
            Utilities.MyClassInit();
        }

        [TestCleanup]
        public void TestCleanup()
        {
            Utilities.MyClassDone();
        }

        /// <summary>
        ///A test for Render
        ///</summary>
        [TestMethod()]
        public void TestRenderWithNoPlugins()
        {
            RenderEngine target = new RenderEngine();
            var actual = target.Render("Dude", "www.fnal.gov");
            Assert.AreEqual(0, actual.Count(), "Expected nothing to be coming back there!");
        }

        [PaperRender("Dude")]
        class RenderTemp : IPaperRender
        {
            /// <summary>
            /// Return a dummy!
            /// </summary>
            /// <param name="renderAddress"></param>
            /// <returns></returns>
            public IEnumerable<PivotImage> Render(string renderAddress)
            {
                PivotImage img = new PivotImage(null);
                yield return img;
            }
        }

        [PaperRender("Fork")]
        class RenderTemp2 : IPaperRender
        {
            /// <summary>
            /// Return a dummy!
            /// </summary>
            /// <param name="renderAddress"></param>
            /// <returns></returns>
            public IEnumerable<PivotImage> Render(string renderAddress)
            {
                PivotImage img = new PivotImage(null);
                yield return img;
                yield return img;
            }
        }

        [TestMethod]
        public void TestRenderWithWrongPlugin()
        {
            RenderEngine target = new RenderEngine();

            Utilities.AddPart(new RenderTemp());
            Utilities.Compose(target);

            var actual = target.Render("Fork", "www.fnal.gov");
            Assert.AreEqual(0, actual.Count(), "Expected nothing to come back!");
        }

        [TestMethod]
        public void TestRenderWithRightPlugin()
        {
            RenderEngine target = new RenderEngine();

            Utilities.AddPart(new RenderTemp());
            Utilities.Compose(target);

            var actual = target.Render("Dude", "www.fnal.gov");
            Assert.AreEqual(1, actual.Count(), "Expected nothing to come back!");
        }

        [TestMethod]
        public void TestRenderWithTwoPlugins()
        {
            RenderEngine target = new RenderEngine();

            Utilities.AddPart(new RenderTemp());
            Utilities.AddPart(new RenderTemp2());
            Utilities.Compose(target);

            var actual = target.Render("Dude", "www.fnal.gov");
            Assert.AreEqual(1, actual.Count(), "Expected one to come back!");

            actual = target.Render("Fork", "www.cnn.com");
            Assert.AreEqual(2, actual.Count(), "Expected two to come back!");
        }

        /// <summary>
        ///A test for RenderEngine Constructor
        ///</summary>
        [TestMethod()]
        public void RenderEngineConstructorTest()
        {
            RenderEngine target = new RenderEngine();
        }

        [PaperRender("throwAtStart")]
        public class RenderThrowDuringInitialRender : IPaperRender
        {
            public IEnumerable<PivotImage> Render(string renderAddress)
            {
                throw new NotImplementedException();
            }
        }

        [PaperRender("throwAfterTwo")]
        public class RenderThrowAfterTwoImages : IPaperRender
        {
            public IEnumerable<PivotImage> Render(string renderAddress)
            {
                PivotImage img = new PivotImage(null);
                yield return img;
                yield return img;
                throw new InvalidOperationException("No way!");
            }
        }

        [TestMethod]
        public void TestThrowingEngine()
        {
            RenderEngine target = new RenderEngine();

            Utilities.AddPart(new RenderThrowDuringInitialRender());
            Utilities.Compose(target);

            var result = target.Render("throwAtStart", "dude");
            Assert.AreEqual(0, result.Count(), "expected no results for this rendering!"); 
        }

        [TestMethod]
        public void TestThrowAfterStart()
        {
            RenderEngine target = new RenderEngine();

            Utilities.AddPart(new RenderThrowAfterTwoImages());
            Utilities.Compose(target);

            var result = target.Render("throwAfterTwo", "dude");
            Assert.AreEqual(2, result.Count(), "Should have gotten two there!");
        }

        [TestMethod]
        public void TestDuplicateRequests()
        {
            RenderEngine target = new RenderEngine();
            Utilities.AddPart(new RenderTemp());
            Utilities.AddPart(new RenderTemp2());
            Utilities.Compose(target);

            var r1 = target.Render("Dude", "http://www.fnal.gov/releases");
            var r2 = target.Render("Dude", "http://www.fnal.gov/releases");

            Assert.AreEqual(0, r2.Count(), "Expected second rendering to return no images because it is a duplicate!");

            var r3 = target.Render("Dude", "http://www.fnal.gov/releases/");

            Assert.AreEqual(0, r3.Count(), "There should be no difference between a / and no slash");

            var r4 = target.Render("Dude", "http://www.fnal.gov/releases/junk/");
            var r5 = target.Render("Dude", "http://www.fnal.gov/releases/junk");

            Assert.AreEqual(1, r4.Count(), "Shoudl have rendered - substring shouldn't have caused trouble!");
            Assert.AreEqual(0, r5.Count(), "Expected there to be no rendering when slash done first!");

            var r6 = target.Render("Fork", "http://www.fnal.gov/releases");
            Assert.AreEqual(2, r6.Count(), "Same address, different rendering guy should have rendered!");
        }

        [PaperRender("RenderRecursive")]
        class RenderRecursive : IPaperRender
        {
#pragma warning disable 0649
            [Import]
            IPaperRenderEngine MyRenderEngine;
#pragma warning restore 0649

            public IEnumerable<PivotImage> Render(string renderAddress)
            {
                foreach (var item in MyRenderEngine.Render("RenderRecursive", renderAddress))
                {
                    yield return item;
                }

                PivotImage img = new PivotImage(null);
                yield return img;
            }
        }


        [TestMethod]
        public void TestRecursiveDuplicateRequests()
        {
            ///
            /// If we ask to render, and that render asks to render the parent page, make sure
            /// that we don't get stuck in an infinite loop!
            /// 

            RenderEngine target = new RenderEngine();
            Utilities.AddPart(new RenderRecursive());
            Utilities.Compose(target);

            var result = target.Render("RenderRecursive", "http://www.nytimes.com/doit.html");
        }

        [TestMethod]
        public void TestDuplicateRequestsForFullConfNoteURL()
        {
            RenderEngine target = new RenderEngine();
            Utilities.AddPart(new RenderTemp());
            Utilities.AddPart(new RenderTemp2());
            Utilities.Compose(target);

            var r1 = target.Render("Dude", "https://atlas.web.cern.ch/Atlas/GROUPS/PHYSICS/CONFNOTES/ATLAS-CONF-2010-010");
            var r2 = target.Render("Dude", "https://atlas.web.cern.ch/Atlas/GROUPS/PHYSICS/CONFNOTES/ATLAS-CONF-2010-010/");

            Assert.AreEqual(1, r1.Count(), "Expected to have the first one do some rendering!");
            Assert.AreEqual(0, r2.Count(), "Expected the second try to have nothing to render!");
        }
    }
}
